|
Example
3:
Compute
an absolute value of $1, store in $1 and return
branches
+ jumps: modify PC (eg jr)
beq:
branch is two registers have equal contents
- increment PC by a given #
of words
bne:
branch if not equal
slt:
set less than
Address
|
Instruction
|
0000
0000
0000
0004
0000
0008
0000
000c
|
slt
$2, $1, $0 ;(compare $1 < 0)
beq
$2, $0, 1 ;if false, skipover
sub
$1, $0, $1 ;negates $1
jr
$31
|
Example:
Looping
sum
the integers 1..13, store in $3, return
Address
|
Instruction
|
0000
0000
0000
0004
0000
0008
0000
000c
0000
0010
0000
0014
0000
0018
0000
001c
|
lis
$2 ;$2 <- 13
.word
13
add
$3, $0, $0 ;$3 <- 0
add
$2, $3, $2 ;$3 += $2
lis
$1 ;$1 <- 1
.word
1
sub
$2, $2, $1
bne
$0, $0, -5
|
RAM
lw –
“load word”
- lw $a, i($b)
- load the word at MEM[$b +
i] into $a
sw –
“store word”
- sw $a, i($b)
- store the word $a at
MEM[$b + i]
multiply
- product of 2 32-bit
numbers is 64 bits; too big for a register
- So two special registers,
hi + lo, store the result of mult (and div)
- mult $a, $b = hi:lo <-
$a * $b
- (for division, lo stores
quotient, hi stores remainder)
mflo –
move from lo
mfhi –
move from hi
Example
5
$1 =
address of an array
$2 =
length of the array
Place
element 5 (6th starting from 0) into $3
lw
$3, 20($1) ;5x4, array slots are
4 bytes
jr
$31
|
If the
index is not known:
lis
$5 ;$5 = index I want
.word
______
lis
$4
.word
4
mult
$5, $4
mflo
$5 ;$5 *= 5
add
$5, $1, $5 ;$5 += $1
lw
$3, 0($5) ;$3 <- MEM[$5]
jr
$31
|
Revisiting loop example:
Improvement:
you can take out the lis and .word 1 out of the loop to make the loop run
faster.
- have to make sure the
branch index is still consistent
- when explicit branching
exists
- adding/removing
instructions => change branch offsets
- Instead, the assembler
allows labeled instructions:
label:
instruction
foo:
add $1, $2, $3
|
The
assembler associates the name foo with the address of add $1, $2, $3 in the
binary.
lis $2
.word 13
add $3, $0, $0
top: ;top = 0x0c
add $3, $3, $2
lis $1
.word 1
sub $2, $2, $1
bne $2, $0, top
jr $31 ;20
|
assembler
computes the difference between PC and top, in words
- ie (top – PC)/4 = (0C –
20)/4 = -5
Procedures
Two
problems to be solved
- call and return
- how to transfer control
into and out of the procedure
- registers
- what if a procedure f
overwrites the main line’s data?
- we could reserve some
registers for f and some for the mainline – with no overlap
- Instead, guarantee that
procedure leave registers unchanged when done.
- Which
RAM? How do we keep procedures from using the same RAM?
- solution: allocate memory from the top or bottom of free
RAM. Need to keep track of which RAM is used and which RAM isn’t.
- Machine
helps us out. $30 initialized (by the loader) to just past the last
word of memory. We can use $30 as a “bookmark” to separate used &
unused RAM if we allocate from the bottom.
Example
f
calls g
g calls h
h returns
g returns
h
returns
|
RAM:
Code
|
|
|
h
save
|
g
save
|
f
save
|
|
$30
gets changed accordingly (like a stack)
- strategy: each procedure
pushes the registers it will use onto the stack, and pops the original
values from the stack when done.
- $30 – the stack pointer –
contains the address of the top of the stack
Template for writing procedures
f:
sw $2, -4($30)
sw $3, -8($30) ; push registers f will modify onto
stack
lis $3
.word 8
sub $30, $30, $3 ; decrement stack ptr
<body>
add $30, $30, $3 ; increment stack ptr
lw $3, -8($30)
lw $2, -8($30)
<return>
|
|
|
|